import { Request, Response } from 'express';
import { File, IFile } from '../models/File';
import { AuthRequest } from '../middleware/auth';
import { logger } from '../utils/logger';
import { getFileTypeConfig } from '../config/fileTypes';
import { getFileUrl } from '../config/storage';
import mongoose from 'mongoose';
import fs from 'fs';
import path from 'path';

export class FileController {
  // 上传单个文件
  public upload = async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      if (!req.user) {
        logger.warn('文件上传失败: 用户未认证');
        res.status(401).json({
          success: false,
          message: '用户认证失败',
          code: 'UNAUTHENTICATED'
        });
        return;
      }

      if (!req.file) {
        logger.warn('文件上传失败: 未提供文件', { userId: req.user.id });
        res.status(400).json({
          success: false,
          message: '请选择要上传的文件',
          code: 'NO_FILE_PROVIDED'
        });
        return;
      }

      const { relatedLessonPlan, isPublic = true } = req.body;

      logger.info('开始上传文件', { 
        userId: req.user.id, 
        fileName: req.file.originalname,
        fileSize: req.file.size,
        mimeType: req.file.mimetype
      });

      // 验证relatedLessonPlan ID格式
      if (relatedLessonPlan && !mongoose.Types.ObjectId.isValid(relatedLessonPlan)) {
        // 删除已上传的文件
        if (fs.existsSync(req.file.path)) {
          fs.unlinkSync(req.file.path);
        }
        
        logger.warn('文件上传失败: 无效的教案ID', { userId: req.user.id, relatedLessonPlan });
        res.status(400).json({
          success: false,
          message: '无效的教案ID',
          code: 'INVALID_LESSON_PLAN_ID'
        });
        return;
      }

      const fileData = new File({
        filename: req.file.filename,
        originalname: req.file.originalname,
        path: req.file.path,
        size: req.file.size,
        mimetype: req.file.mimetype,
        uploader: req.user.id,
        relatedLessonPlan: relatedLessonPlan || undefined,
        isPublic: isPublic === 'true' || isPublic === true
      });

      await fileData.save();

      // 填充上传者信息
      await fileData.populate('uploader', 'name email');

      logger.info('文件上传成功', { 
        userId: req.user.id, 
        fileId: fileData._id,
        fileName: req.file.originalname,
        fileSize: req.file.size
      });

      res.status(201).json({
        success: true,
        message: '文件上传成功',
        data: {
          id: fileData._id,
          filename: fileData.filename,
          originalname: fileData.originalname,
          size: fileData.size,
          mimetype: fileData.mimetype,
          url: getFileUrl(fileData.path),
          isPublic: fileData.isPublic,
          uploader: fileData.uploader,
          relatedLessonPlan: fileData.relatedLessonPlan,
          createdAt: fileData.createdAt,
          updatedAt: fileData.updatedAt
        }
      });
    } catch (error: any) {
      logger.error('文件上传错误:', { error: error.message, userId: req.user?.id, stack: error.stack });
      
      // 如果保存到数据库失败，删除已上传的文件
      if (req.file && req.file.path) {
        try {
          fs.unlinkSync(req.file.path);
        } catch (unlinkError) {
          logger.error('删除文件失败:', { error: unlinkError });
        }
      }

      res.status(500).json({
        success: false,
        message: '文件上传失败'
      });
    }
  };

  // 批量上传文件
  public uploadMultiple = async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      if (!req.user) {
        logger.warn('批量文件上传失败: 用户未认证');
        res.status(401).json({
          success: false,
          message: '用户认证失败',
          code: 'UNAUTHENTICATED'
        });
        return;
      }

      if (!req.files || !Array.isArray(req.files) || req.files.length === 0) {
        logger.warn('批量文件上传失败: 未提供文件', { userId: req.user.id });
        res.status(400).json({
          success: false,
          message: '请选择要上传的文件',
          code: 'NO_FILES_PROVIDED'
        });
        return;
      }

      if (req.files.length > 10) {
        logger.warn('批量文件上传失败: 文件数量超限', { userId: req.user.id, fileCount: req.files.length });
        res.status(400).json({
          success: false,
          message: '一次最多只能上传10个文件',
          code: 'TOO_MANY_FILES'
        });
        return;
      }

      const { relatedLessonPlan, isPublic = true } = req.body;
      const uploadedFiles: IFile[] = [];

      logger.info('开始批量上传文件', { 
        userId: req.user.id, 
        fileCount: req.files.length,
        totalSize: req.files.reduce((sum, file) => sum + file.size, 0)
      });

      // 验证relatedLessonPlan ID格式
      if (relatedLessonPlan && !mongoose.Types.ObjectId.isValid(relatedLessonPlan)) {
        // 删除所有已上传的文件
        for (const file of req.files) {
          if (fs.existsSync(file.path)) {
            fs.unlinkSync(file.path);
          }
        }
        
        logger.warn('批量文件上传失败: 无效的教案ID', { userId: req.user.id, relatedLessonPlan });
        res.status(400).json({
          success: false,
          message: '无效的教案ID',
          code: 'INVALID_LESSON_PLAN_ID'
        });
        return;
      }

      try {
        for (const file of req.files) {
          const fileData = new File({
            filename: file.filename,
            originalname: file.originalname,
            path: file.path,
            size: file.size,
            mimetype: file.mimetype,
            uploader: req.user.id,
            relatedLessonPlan: relatedLessonPlan || undefined,
            isPublic: isPublic === 'true' || isPublic === true
          });

          await fileData.save();
          await fileData.populate('uploader', 'name email');
          uploadedFiles.push(fileData);
        }

        logger.info('批量文件上传成功', { 
          userId: req.user.id, 
          fileCount: uploadedFiles.length,
          fileIds: uploadedFiles.map(f => f._id)
        });

        res.status(201).json({
          success: true,
          message: `成功上传 ${uploadedFiles.length} 个文件`,
          data: uploadedFiles.map(file => ({
            id: file._id,
            filename: file.filename,
            originalname: file.originalname,
            size: file.size,
            mimetype: file.mimetype,
            url: getFileUrl(file.path),
            isPublic: file.isPublic,
            uploader: file.uploader,
            relatedLessonPlan: file.relatedLessonPlan,
            createdAt: file.createdAt,
            updatedAt: file.updatedAt
          }))
        });
      } catch (error: any) {
        // 如果有文件保存失败，删除所有已上传的文件
        for (const file of req.files) {
          try {
            fs.unlinkSync(file.path);
          } catch (unlinkError) {
            logger.error('删除文件失败:', { error: unlinkError });
          }
        }

        // 删除已保存到数据库的文件记录
        for (const uploadedFile of uploadedFiles) {
          await File.findByIdAndDelete(uploadedFile._id);
        }

        throw error;
      }
    } catch (error: any) {
      logger.error('批量文件上传错误:', { error: error.message, userId: req.user?.id, stack: error.stack });
      res.status(500).json({
        success: false,
        message: '批量文件上传失败，请稍后重试',
        code: 'INTERNAL_ERROR'
      });
    }
  };

  // 下载文件
  public download = async (req: Request, res: Response): Promise<void> => {
    try {
      const { id } = req.params;

      if (!mongoose.Types.ObjectId.isValid(id)) {
        logger.warn('文件下载失败: 无效的文件ID', { fileId: id });
        res.status(400).json({
          success: false,
          message: '无效的文件ID',
          code: 'INVALID_FILE_ID'
        });
        return;
      }

      const file = await File.findById(id);
      if (!file) {
        logger.warn('文件下载失败: 文件不存在', { fileId: id });
        res.status(404).json({
          success: false,
          message: '文件不存在',
          code: 'FILE_NOT_FOUND'
        });
        return;
      }

      // 检查文件是否为公开文件
      if (!file.isPublic) {
        logger.warn('文件下载失败: 没有权限访问', { fileId: id, isPublic: file.isPublic });
        res.status(403).json({
          success: false,
          message: '没有权限访问此文件',
          code: 'ACCESS_DENIED'
        });
        return;
      }

      // 检查文件是否存在于磁盘上
      if (!fs.existsSync(file.path)) {
        logger.error('文件下载失败: 文件不存在于磁盘', { fileId: id, filePath: file.path });
        res.status(404).json({
          success: false,
          message: '文件不存在',
          code: 'FILE_NOT_FOUND_ON_DISK'
        });
        return;
      }

      // 增加下载次数
      await File.findByIdAndUpdate(id, { $inc: { downloads: 1 } });

      logger.info('文件下载开始', { fileId: id, fileName: file.originalname });

      // 设置响应头
      res.setHeader('Content-Type', file.mimetype);
      res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(file.originalname)}"`);

      // 发送文件
      res.sendFile(path.resolve(file.path));
    } catch (error: any) {
      logger.error('文件下载错误:', { error: error.message, fileId: req.params.id, stack: error.stack });
      res.status(500).json({
        success: false,
        message: '文件下载失败，请稍后重试',
        code: 'INTERNAL_ERROR'
      });
    }
  };

  // 删除文件
  public delete = async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      const { id } = req.params;

      if (!mongoose.Types.ObjectId.isValid(id)) {
        logger.warn('删除文件失败: 无效的文件ID', { fileId: id });
        res.status(400).json({
          success: false,
          message: '无效的文件ID',
          code: 'INVALID_FILE_ID'
        });
        return;
      }

      if (!req.user) {
        logger.warn('删除文件失败: 用户未认证');
        res.status(401).json({
          success: false,
          message: '用户认证失败',
          code: 'UNAUTHENTICATED'
        });
        return;
      }

      logger.info('删除文件请求', { fileId: id, userId: req.user.id });

      const file = await File.findById(id);
      if (!file) {
        logger.warn('删除文件失败: 文件不存在', { fileId: id, userId: req.user.id });
        res.status(404).json({
          success: false,
          message: '文件不存在',
          code: 'FILE_NOT_FOUND'
        });
        return;
      }

      // 检查权限：只有上传者和管理员可以删除
      if (file.uploader.toString() !== req.user.id && req.user.role !== 'admin') {
        logger.warn('删除文件失败: 权限不足', { 
          fileId: id, 
          userId: req.user.id, 
          uploaderID: file.uploader.toString(),
          userRole: req.user.role 
        });
        res.status(403).json({
          success: false,
          message: '没有权限删除此文件',
          code: 'ACCESS_DENIED'
        });
        return;
      }

      // 删除磁盘上的文件
      try {
        if (fs.existsSync(file.path)) {
          fs.unlinkSync(file.path);
          logger.info('删除磁盘文件成功', { fileId: id, filePath: file.path });
        }
      } catch (unlinkError) {
        logger.error('删除磁盘文件失败:', { error: unlinkError, filePath: file.path });
      }

      // 删除数据库记录
      await File.findByIdAndDelete(id);

      logger.info('文件删除成功', { 
        fileId: id, 
        fileName: file.originalname,
        userId: req.user.id 
      });

      res.json({
        success: true,
        message: '文件删除成功'
      });
    } catch (error: any) {
      logger.error('删除文件错误:', { error: error.message, fileId: req.params.id, userId: req.user?.id, stack: error.stack });
      res.status(500).json({
        success: false,
        message: '删除文件失败，请稍后重试',
        code: 'INTERNAL_ERROR'
      });
    }
  };

  // 文件预览
  public preview = async (req: Request, res: Response): Promise<void> => {
    try {
      const { id } = req.params;

      if (!mongoose.Types.ObjectId.isValid(id)) {
        logger.warn('文件预览失败: 无效的文件ID', { fileId: id });
        res.status(400).json({
          success: false,
          message: '无效的文件ID',
          code: 'INVALID_FILE_ID'
        });
        return;
      }

      const file = await File.findById(id).populate('uploader', 'name email');
      if (!file) {
        logger.warn('文件预览失败: 文件不存在', { fileId: id });
        res.status(404).json({
          success: false,
          message: '文件不存在',
          code: 'FILE_NOT_FOUND'
        });
        return;
      }

      // 检查文件是否为公开文件
      if (!file.isPublic) {
        logger.warn('文件预览失败: 没有权限访问', { fileId: id, isPublic: file.isPublic });
        res.status(403).json({
          success: false,
          message: '没有权限访问此文件',
          code: 'ACCESS_DENIED'
        });
        return;
      }

      // 检查文件是否存在于磁盘上
      if (!fs.existsSync(file.path)) {
        logger.error('文件预览失败: 文件不存在于磁盘', { fileId: id, filePath: file.path });
        res.status(404).json({
          success: false,
          message: '文件不存在',
          code: 'FILE_NOT_FOUND_ON_DISK'
        });
        return;
      }

      // 获取文件类型配置
      const fileConfig = getFileTypeConfig(file.mimetype);
      const fileCategory = fileConfig?.category || 'unknown';

      // 获取文件统计信息
      const stats = fs.statSync(file.path);

      // 基础预览信息
      const previewData: any = {
        id: file._id,
        filename: file.filename,
        originalname: file.originalname,
        mimetype: file.mimetype,
        size: file.size,
        category: fileCategory,
        uploader: file.uploader,
        uploadDate: file.createdAt,
        downloads: file.downloads,
        isPublic: file.isPublic,
        fileStats: {
          size: stats.size,
          createdAt: stats.birthtime,
          modifiedAt: stats.mtime
        }
      };

      // 根据文件类型提供不同的预览信息
      switch (fileCategory) {
        case 'image':
          // 图片文件预览
          previewData.preview = {
            type: 'image',
            url: getFileUrl(file.path),
            thumbnailUrl: getFileUrl(file.path), // 实际项目中应该生成缩略图
            canDisplay: true
          };
          break;

        case 'document':
          // 文档文件预览
          if (file.mimetype === 'text/plain') {
            // 文本文件可以读取部分内容
            try {
              const content = fs.readFileSync(file.path, 'utf8');
              const maxLength = 1000; // 预览前1000个字符
              previewData.preview = {
                type: 'text',
                content: content.length > maxLength 
                  ? content.substring(0, maxLength) + '...' 
                  : content,
                totalLength: content.length,
                canDisplay: true
              };
            } catch (readError) {
              logger.error('读取文本文件失败', { fileId: id, error: readError });
              previewData.preview = {
                type: 'document',
                canDisplay: false,
                message: '无法读取文件内容'
              };
            }
          } else if (file.mimetype === 'application/pdf') {
            // PDF文件
            previewData.preview = {
              type: 'pdf',
              url: getFileUrl(file.path),
              canDisplay: true,
              message: 'PDF文件可以在浏览器中直接查看'
            };
          } else {
            // 其他文档类型
            previewData.preview = {
              type: 'document',
              canDisplay: false,
              downloadUrl: `/api/files/download/${file._id}`,
              message: '此文件类型不支持预览，请下载后查看'
            };
          }
          break;

        case 'presentation':
        case 'spreadsheet':
          // 演示文稿和电子表格
          previewData.preview = {
            type: fileCategory,
            canDisplay: false,
            downloadUrl: `/api/files/download/${file._id}`,
            message: `${fileCategory === 'presentation' ? '演示文稿' : '电子表格'}文件不支持预览，请下载后查看`
          };
          break;

        case 'archive':
          // 压缩文件
          previewData.preview = {
            type: 'archive',
            canDisplay: false,
            downloadUrl: `/api/files/download/${file._id}`,
            message: '压缩文件不支持预览，请下载后解压查看'
          };
          break;

        default:
          // 未知类型
          previewData.preview = {
            type: 'unknown',
            canDisplay: false,
            downloadUrl: `/api/files/download/${file._id}`,
            message: '未知的文件类型，请下载后查看'
          };
      }

      logger.info('文件预览请求成功', { fileId: id, category: fileCategory });

      res.json({
        success: true,
        data: previewData
      });
    } catch (error: any) {
      logger.error('文件预览错误:', { error: error.message, fileId: req.params.id, stack: error.stack });
      res.status(500).json({
        success: false,
        message: '文件预览失败，请稍后重试',
        code: 'INTERNAL_ERROR'
      });
    }
  };

  // 获取文件列表
  public getFiles = async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      const { page = 1, limit = 10, category, isPublic, uploader } = req.query;
      
      const pageNum = parseInt(page as string);
      const limitNum = parseInt(limit as string);
      
      // 构建查询条件
      const query: any = {};
      
      if (category) {
        const fileConfigs = await import('../config/fileTypes').then(m => m.getFileTypesByCategory(category as string));
        const mimeTypes = fileConfigs.map(config => config.mimeType);
        if (mimeTypes.length > 0) {
          query.mimetype = { $in: mimeTypes };
        }
      }
      
      if (isPublic !== undefined) {
        query.isPublic = isPublic === 'true';
      }
      
      if (uploader && mongoose.Types.ObjectId.isValid(uploader as string)) {
        query.uploader = uploader;
      }
      
      // 如果用户未认证，只能查看公开文件
      if (!req.user) {
        query.isPublic = true;
      }
      
      const skip = (pageNum - 1) * limitNum;
      
      const [files, total] = await Promise.all([
        File.find(query)
          .populate('uploader', 'name email')
          .populate('relatedLessonPlan', 'title')
          .sort({ createdAt: -1 })
          .skip(skip)
          .limit(limitNum),
        File.countDocuments(query)
      ]);
      
      logger.info('获取文件列表成功', { 
        userId: req.user?.id,
        page: pageNum,
        limit: limitNum,
        total,
        query
      });
      
      res.json({
        success: true,
        data: {
          files: files.map(file => ({
            id: file._id,
            filename: file.filename,
            originalname: file.originalname,
            size: file.size,
            mimetype: file.mimetype,
            url: getFileUrl(file.path),
            isPublic: file.isPublic,
            uploader: file.uploader,
            relatedLessonPlan: file.relatedLessonPlan,
            downloads: file.downloads,
            createdAt: file.createdAt,
            updatedAt: file.updatedAt
          })),
          pagination: {
            page: pageNum,
            limit: limitNum,
            total,
            totalPages: Math.ceil(total / limitNum)
          }
        }
      });
    } catch (error: any) {
      logger.error('获取文件列表错误:', { error: error.message, userId: req.user?.id, stack: error.stack });
      res.status(500).json({
        success: false,
        message: '获取文件列表失败，请稍后重试',
        code: 'INTERNAL_ERROR'
      });
    }
  };
}